import { DirectiveBinding, ObjectDirective } from 'vue'
import './waves.css'

interface WavesOptions {
  ele: HTMLElement;
  type: 'hit' | 'center';
  color: string;
}

const wavesDirective: ObjectDirective<HTMLElement> = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    const handleClick = (e: MouseEvent) => {
      const customOpts = Object.assign({}, binding.value as Partial<WavesOptions>)
      const opts = Object.assign<WavesOptions, Partial<WavesOptions>>({
        ele: el, // 波纹作用元素
        type: 'hit', // hit 点击位置扩散 center中心点扩展
        color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
      },
      customOpts
      )
      const target = opts.ele
      if (target) {
        target.style.position = 'relative'
        target.style.overflow = 'hidden'
        const rect = target.getBoundingClientRect()
        let ripple = target.querySelector('.waves-ripple') as HTMLElement
        if (!ripple) {
          ripple = document.createElement('span')
          ripple.className = 'waves-ripple'
          ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
          target.appendChild(ripple)
        } else {
          ripple.className = 'waves-ripple'
        }
        switch (opts.type) {
          case 'center':
            ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
            ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
            break
          default:
            ripple.style.top =
              (e.pageY - rect.top - ripple.offsetHeight / 2 - (document.documentElement.scrollTop || document.body.scrollTop)) + 'px'
            ripple.style.left =
              (e.pageX - rect.left - ripple.offsetWidth / 2 - (document.documentElement.scrollLeft || document.body.scrollLeft)) + 'px'
        }
        ripple.style.backgroundColor = opts.color
        ripple.className = 'waves-ripple z-active'
        return false
      }
    }

    el.addEventListener('click', handleClick, false)

    // 存储清理函数，以便在 unmounted 时调用
    el._wavesRemove = () => {
      el.removeEventListener('click', handleClick, false)
    }
  },

  unmounted(el: HTMLElement) {
    const remove = (el as any)._wavesRemove
    if (remove) {
      remove()
      delete (el as any)._wavesRemove
    }
  }
}

export default wavesDirective
